﻿#include "ais_base.h"
#include "renderer/renderer.h"

CAGD::AIS_Base::AIS_Base() : m_context(AIS_Context::ShareContext())
{
    CAGD_INIT_MNT(AIS_Base);

    // 初始化数据
    m_info.status = AIS_Status::NONE;
    m_info.index = 0;
    m_info.size = 0;
    m_info.psize = 1;
    m_info.diffuseTex = 0;
    m_info.specularTex = 0;
    m_info.reflactTex = 0;
    m_info.reflectTex = 0;
    m_info.depth = 2;
    m_info.smooth = false;
    m_info.active = true;
    m_info.shine = false;
    m_info.color = {1, 1, 1, 1};
}

CAGD::AIS_Base::~AIS_Base()
{
    CAGD_DEL_MNT();
}

CAGD::AIS_Base *CAGD::AIS_Base::GetParent() const
{
    if (m_node->parent != nullptr)
        return m_node->parent->value;
    else
        return nullptr;
}

CAGD::AIS_Base *CAGD::AIS_Base::GetChild(AIS_Type type, int i) const
{
    int j = 0;
    for (auto p : m_node->children)
    {
        if (p->value->GetType() == type)
        {
            if (j < i)
                j++;
            else
                return p->value;
        }
    }
    return nullptr;
}

void CAGD::AIS_Base::AddParent(Handle(AIS_Base) parent)
{
    m_tree->Insert(parent->GetNode(), m_node);
}

void CAGD::AIS_Base::RemoveParent()
{
    if (m_node->parent != nullptr)
    {
        auto &children = m_node->parent->children;
        for (auto it = children.begin(); it != children.end(); ++it)
        {
            if (*it == m_node)
            {
                children.erase(it);
                break;
            }
        }
        m_node->parent = nullptr;
    }
}

void CAGD::AIS_Base::AddChild(Handle(AIS_Base) child)
{
    m_tree->Insert(m_node, child->GetNode());
}

void CAGD::AIS_Base::RemoveChildren()
{
    // 先解除绑定
    for (auto c : m_node->children)
        c->parent = nullptr;

    // 发送 Dead 消息
    PassMessageDown(Message::DEAD);
    m_node->children.clear();
}

void CAGD::AIS_Base::PassMessageUp(Message mess)
{
    if (m_node->parent != nullptr)
        m_node->parent->value->RecvMessage(mess);
}

void CAGD::AIS_Base::PassMessageDown(Message mess)
{
    for (auto node : m_node->children)
        node->value->RecvMessage(mess);
}

bool CAGD::AIS_Base::MoveTo(Point pos)
{
    return false;
}

bool CAGD::AIS_Base::Move(Point pos)
{
    return false;
}

bool CAGD::AIS_Base::Click(Point pos)
{
    bool hang = MoveTo(pos);
    if (hang)
        m_info.status = AIS_Status::TOUCH;
    return hang;
}

bool CAGD::AIS_Base::Release(Point pos)
{
    // 暂不处理
    return false;
}

void CAGD::AIS_Base::RecvMessage(Message mess)
{
    switch (mess)
    {
    case CAGD::Message::SHOW: {
        if (m_info.status == AIS_Status::HIDDEN)
            m_info.status = AIS_Status::NONE;
        PassMessageDown(Message::SHOW);
        break;
    }
    case CAGD::Message::HIDE: {
        if (m_info.status == AIS_Status::NONE)
            m_info.status = AIS_Status::HIDDEN;
        PassMessageDown(Message::HIDE);
        break;
    }
    case CAGD::Message::MOVE_PARENT: {
        // 没有隐藏时才刷新
        if (m_info.status != AIS_Status::HIDDEN)
            UpdateArray();

        // 向下层传递点移动的消息
        PassMessageDown(Message::MOVE_PARENT);
        break;
    }
    case CAGD::Message::MOVE_CHILD: {
        // 没有隐藏时才刷新
        if (m_info.status != AIS_Status::HIDDEN)
            UpdateArray();

        // 向上层传递点移动的消息
        if (m_node->parent == nullptr)
            PassMessageDown(Message::MOVE_PARENT);
        else
            PassMessageUp(Message::MOVE_CHILD);
        break;
    }
    case CAGD::Message::DEAD: {
        // 标记上下元素
        if (m_info.status != AIS_Status::DEAD)
        {
            m_info.status = AIS_Status::DEAD;
            PassMessageUp(Message::DEAD);
            PassMessageDown(Message::DEAD);
        }
        break;
    }
    case CAGD::Message::SELECT: {
        m_info.status = AIS_Status::TOUCH;
        break;
    }
    case CAGD::Message::RELEASE: {
        // 向上层发送 release 消息
        PassMessageUp(Message::RELEASE);
        break;
    }
    default:
        break;
    }
}

void CAGD::AIS_Base::UpdateArray()
{
    // 刷新渲染器
    if (m_renderer != nullptr)
        m_renderer->UpdateArray(this);
}

CAGD::AIS_Info &CAGD::AIS_Base::GetInfo()
{
    return m_info;
}

bool CAGD::AIS_Base::UpdateDepth()
{
    // 隐藏物体不参与比较
    if (m_info.status != AIS_Status::HIDDEN)
    {
        // 为了防止浮点比较的问题，将比较深度设为最浅和次浅的平均
        auto &context = m_context;
        double depth = context.GetDepth();
        if (context.GetInfo().mouseStatus == MouseStatus::HANG && m_info.depth > depth &&
            m_info.status != AIS_Status::TOUCH)
            m_info.status = AIS_Status::NONE;
        if (context.GetInfo().mouseStatus == MouseStatus::TOUCH && m_info.depth > depth)
            m_info.status = AIS_Status::NONE;
    }

    // 重置深度
    m_info.depth = 2;

    // 返回当前物体更新后是否还被选中
    return m_info.status == AIS_Status::TOUCH;
}

void CAGD::AIS_Base::UpdateUniform()
{
    // 刷新渲染器
    if (m_renderer != nullptr)
        m_renderer->UpdateUniform(this);
}

void CAGD::AIS_Base::SetDepth(double depth)
{
    // 刷新深度
    m_info.depth = std::min(depth, m_info.depth);
    m_context.SetDepth(m_info.depth);
}

void CAGD::AIS_Base::SetActive(bool active)
{
    m_info.active = active;
    for (auto &c : m_node->children)
        c->value->SetActive(active);
}

void CAGD::AIS_Base::RegisterRenderer(MainOpenGLWidget *parent)
{
    // 通过工厂构建渲染器
    if (m_renderer == nullptr)
    {
        RendererFactory &factory = RendererFactory::CreateFactory();
        m_renderer = factory.CreateProduct(GetType(), parent);
        m_renderer->UpdateArray(this);
    }
}

void CAGD::AIS_Base::Draw()
{
    if (m_renderer != nullptr && m_info.status != AIS_Status::HIDDEN)
    {
        this->UpdateInfo();
        m_renderer->UpdateUniform(this);
        m_renderer->Draw(this);
    }
}